#include "preloader.h"

#define MAX_EVENTS 10240

static int epfd = -1;
static struct epoll_event epoll_events[MAX_EVENTS];

static int epollInit(void)
{
	epfd = epoll_create(MAX_EVENTS);
	if (epfd < 0)
	{
		return FAILED;
	}
	memset(epoll_events, 0, sizeof(epoll_events));

	return SUCC;
}

static int epollAdd(const int sockfd, const int events)
{ 
	struct epoll_event evt;

	evt.events = events;
	evt.data.fd = sockfd;
	if (epoll_ctl(epfd, EPOLL_CTL_ADD , sockfd, &evt) < 0) 
	{
		return FAILED;
	}

	return SUCC;
}

static int epollDel(const int sockfd)
{
	if (epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL))
	{
			printf("%s\n", strerror(errno));
			plog(ERROR, "del error in Epoll");
			return FAILED;
	}

	return SUCC;
}

static int epollMod(const int sockfd, const int events)
{ 
	struct epoll_event evt;

	evt.events = events;
	evt.data.fd = sockfd;
	if (epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evt))
	{
		return FAILED;
	}

	return SUCC;
}

static int epollWait(EWCB *callback)
{
	int i, sockfd, nfds;

	nfds = epoll_wait(epfd, epoll_events, MAX_EVENTS, EPOLL_TIMEOUT);
	if (nfds < 0)
	{
		return FAILED;
	} 
	if (0 == nfds)
		return SUCC;
	for (i = 0 ; i < nfds; ++i)
	{
		sockfd = epoll_events[i].data.fd;
		if (epoll_events[i].events & EPOLLIN)
			callback(EPOLL_IN, sockfd);
		
	}

	return SUCC;
}

static int epollDestroy(void)
{
	close(epfd);

	return SUCC;
}

int detectEpollCall(const int calltype, const int sockfd, const int event, EWCB *callback)
{
	switch (calltype)
	{
		case EPOLL_INIT:
			return epollInit();
		case EPOLL_ADD:
			return epollAdd(sockfd, event);
		case EPOLL_MOD:
			return epollMod(sockfd, event);
		case EPOLL_WAIT:
			return epollWait(callback);
		case EPOLL_DEL:
			return epollDel(sockfd);
		case EPOLL_DESTROY:
			return epollDestroy();
		default:
			return FAILED;
	}

	return SUCC;
}

